package jfconfig;

/**
 * Created : May 17, 2012
 *
 * @author pquiring
 */

import java.awt.*;
import java.util.*;

import javaforce.*;

public class PrintersAddDialog extends javax.swing.JDialog {

  /**
   * Creates new form PrintersAddDialog
   */
  public PrintersAddDialog(java.awt.Frame parent, boolean modal) {
    super(parent, modal);
    initComponents();
    setPosition();
    listMakes();
  }

  /**
   * This method is called from within the constructor to initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is always
   * regenerated by the Form Editor.
   */
  @SuppressWarnings("unchecked")
  // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
  private void initComponents() {

    jLabel1 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    jLabel3 = new javax.swing.JLabel();
    scanLocal = new javax.swing.JButton();
    localPrinters = new javax.swing.JComboBox();
    addLocal = new javax.swing.JButton();
    jLabel4 = new javax.swing.JLabel();
    ipAddr = new javax.swing.JTextField();
    addIP = new javax.swing.JButton();
    jLabel5 = new javax.swing.JLabel();
    jLabel6 = new javax.swing.JLabel();
    server = new javax.swing.JTextField();
    share = new javax.swing.JTextField();
    addShare = new javax.swing.JButton();
    cancel = new javax.swing.JButton();
    jLabel7 = new javax.swing.JLabel();
    make = new javax.swing.JComboBox();
    jLabel8 = new javax.swing.JLabel();
    model = new javax.swing.JComboBox();
    jLabel9 = new javax.swing.JLabel();
    jLabel10 = new javax.swing.JLabel();
    pass = new javax.swing.JPasswordField();
    user = new javax.swing.JTextField();

    setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

    jLabel1.setText("Add Local Printer");

    jLabel2.setText("Add IP Printer");

    jLabel3.setText("Add Shared Printer");

    scanLocal.setText("Scan");
    scanLocal.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        scanLocalActionPerformed(evt);
      }
    });

    addLocal.setText("Add");
    addLocal.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        addLocalActionPerformed(evt);
      }
    });

    jLabel4.setText("IP Address");

    addIP.setText("Add");
    addIP.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        addIPActionPerformed(evt);
      }
    });

    jLabel5.setText("Server");

    jLabel6.setText("Share");

    addShare.setText("Add");
    addShare.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        addShareActionPerformed(evt);
      }
    });

    cancel.setText("Cancel");
    cancel.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        cancelActionPerformed(evt);
      }
    });

    jLabel7.setText("Make");

    make.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Auto" }));
    make.addItemListener(new java.awt.event.ItemListener() {
      public void itemStateChanged(java.awt.event.ItemEvent evt) {
        makeItemStateChanged(evt);
      }
    });

    jLabel8.setText("Model");

    model.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Auto" }));

    jLabel9.setText("User");

    jLabel10.setText("Password");

    user.setText("guest");

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addGap(0, 0, Short.MAX_VALUE)
            .addComponent(cancel))
          .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addComponent(jLabel1)
              .addComponent(jLabel2)
              .addComponent(jLabel3))
            .addGap(0, 0, Short.MAX_VALUE))
          .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
              .addGroup(layout.createSequentialGroup()
                .addComponent(jLabel7)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(make, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
              .addGroup(layout.createSequentialGroup()
                .addComponent(jLabel8)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(model, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
              .addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
                .addGap(12, 12, 12)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                    .addComponent(scanLocal)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(localPrinters, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                  .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                    .addComponent(jLabel4)
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addComponent(ipAddr))
                  .addGroup(layout.createSequentialGroup()
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addComponent(jLabel10)
                      .addComponent(jLabel9)
                      .addComponent(jLabel6)
                      .addComponent(jLabel5))
                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                      .addComponent(server)
                      .addComponent(share)
                      .addComponent(pass)
                      .addComponent(user, javax.swing.GroupLayout.DEFAULT_SIZE, 215, Short.MAX_VALUE))))))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
              .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                .addComponent(addLocal)
                .addComponent(addIP))
              .addComponent(addShare, javax.swing.GroupLayout.Alignment.TRAILING))))
        .addContainerGap())
    );
    layout.setVerticalGroup(
      layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
      .addGroup(layout.createSequentialGroup()
        .addContainerGap()
        .addComponent(jLabel1)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(scanLocal)
          .addComponent(localPrinters, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
          .addComponent(addLocal))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addComponent(jLabel2)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel4)
          .addComponent(ipAddr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
          .addComponent(addIP))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
        .addComponent(jLabel3)
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel5)
          .addComponent(server, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel6)
          .addComponent(share, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel9)
          .addComponent(user, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel10)
          .addComponent(pass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
          .addComponent(addShare))
        .addGap(18, 18, 18)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel7)
          .addComponent(make, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
          .addComponent(jLabel8)
          .addComponent(model, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        .addComponent(cancel)
        .addContainerGap())
    );

    pack();
  }// </editor-fold>//GEN-END:initComponents

  private void cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelActionPerformed
    dispose();
  }//GEN-LAST:event_cancelActionPerformed

  private void scanLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scanLocalActionPerformed
    scan();
  }//GEN-LAST:event_scanLocalActionPerformed

  private void addLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addLocalActionPerformed
    addLocalPrinter();
  }//GEN-LAST:event_addLocalActionPerformed

  private void addIPActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addIPActionPerformed
    addIPPrinter();
  }//GEN-LAST:event_addIPActionPerformed

  private void makeItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_makeItemStateChanged
    listModels();
  }//GEN-LAST:event_makeItemStateChanged

  private void addShareActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addShareActionPerformed
    addSharedPrinter();
  }//GEN-LAST:event_addShareActionPerformed

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JButton addIP;
  private javax.swing.JButton addLocal;
  private javax.swing.JButton addShare;
  private javax.swing.JButton cancel;
  private javax.swing.JTextField ipAddr;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JLabel jLabel10;
  private javax.swing.JLabel jLabel2;
  private javax.swing.JLabel jLabel3;
  private javax.swing.JLabel jLabel4;
  private javax.swing.JLabel jLabel5;
  private javax.swing.JLabel jLabel6;
  private javax.swing.JLabel jLabel7;
  private javax.swing.JLabel jLabel8;
  private javax.swing.JLabel jLabel9;
  private javax.swing.JComboBox localPrinters;
  private javax.swing.JComboBox make;
  private javax.swing.JComboBox model;
  private javax.swing.JPasswordField pass;
  private javax.swing.JButton scanLocal;
  private javax.swing.JTextField server;
  private javax.swing.JTextField share;
  private javax.swing.JTextField user;
  // End of variables declaration//GEN-END:variables

  private String mm[];  //almost 14,000 lines
  private ArrayList<String> ppdList = new ArrayList<String>();

  private void listMakes() {
    JFTask task = new JFTask() {
      public boolean work() {
        this.setLabel("Building drivers list...");
        this.setProgress(-1);
        ShellProcess sp = new ShellProcess();
        String output = sp.run(new String[] {"lpinfo", "-m"}, false);
        mm = output.split("\n");
        String lastMake = "";
        for(int a=0;a<mm.length;a++) {
          String f[] = mm[a].split(" ");  //ppd Make Model ...
          if (!f[1].equalsIgnoreCase(lastMake)) {
            lastMake = f[1];
            make.addItem(lastMake);
          }
        }
        return true;
      }
    };
    ProgressDialog dialog = new ProgressDialog(null, true, task);
    dialog.setAutoClose(true);
    dialog.setVisible(true);
  }

  private void listModels() {
    model.removeAllItems();
    ppdList.clear();
    String currentMake = (String)make.getSelectedItem();
    if (currentMake.equals("Auto")) {
      model.addItem("Auto");
      return;
    }
    for(int a=0;a<mm.length;a++) {
      String f[] = mm[a].split(" ");  //ppd Make Model ...
      if (f[0].indexOf("ppds:1") != -1) continue;  //repeat ???
      if (f[1].equalsIgnoreCase(currentMake)) {
        String pm = f[2];
        for(int b=3;b<f.length;b++) {
          if (f[b].equals("-")) break;
          if (f[b].startsWith("Foomatic/")) break;
          pm += " " + f[b];
        }
        model.addItem(pm);
        ppdList.add(f[0]);
      }
    }
  }

  private void scan() {
    localPrinters.removeAllItems();
    JFTask task = new JFTask() {
      public boolean work() {
        setProgress(-1);
        setLabel("Scanning for local printers...");
        ShellProcess sp = new ShellProcess();
        String output = sp.run(new String[] {"lpinfo", "-v"}, false);
        String lns[] = output.split("\n");
        for(int a=0;a<lns.length;a++) {
          if (lns[a].indexOf(":") == -1) continue;
          int idx = lns[a].indexOf(" ");
          localPrinters.addItem(lns[a].substring(idx+1));
        }
        return true;
      }
    };
    ProgressDialog dialog = new ProgressDialog(null, true, task);
    dialog.setAutoClose(true);
    dialog.setVisible(true);
  }

  private String getPrinterName(String uri) {
    String name = "Printer1";
    int i1 = uri.indexOf("//");
    if (i1 == -1) return name;
    i1 += 2;
    int i2 = uri.indexOf("/", i1);
    if (i2 == -1) return name;
    name = uri.substring(i1, i2);
    return name;
  }

  private String getPPD() {
    String ppd = ppdList.get(model.getSelectedIndex());
    return ppd;
  }

  private void addLocalPrinter() {
    int idx = localPrinters.getSelectedIndex();
    if (idx == -1) return;
    String uri = (String)localPrinters.getSelectedItem();
    String name = JFAWT.getString("Enter Printer Name", getPrinterName(uri));
    ShellProcess sp = new ShellProcess();
    String output = null;
    if (ppdList.isEmpty() || ppdList.get(model.getSelectedIndex()).equals("Auto")) {
      output = sp.run(new String[] {"sudo", "lpadmin", "-E", "-p", name, "-v", uri}, false);
    } else {
      String ppd = getPPD();
      output = sp.run(new String[] {"sudo", "lpadmin", "-E", "-p", name, "-v", uri, "-m", ppd}, false);
    }
    if (sp.getErrorLevel() != 0) {
      JFLog.log("cmd=" + sp.command);
      JFAWT.showError("Error", "Unable to add printer:\n"+output);
    }
    dispose();
  }

  private void addIPPrinter() {
    String ip = ipAddr.getText();
    if (ip.length() == 0) return;
    if (ppdList.isEmpty()) {
      JFAWT.showError("Error", "Must specify a printer make/model");
      return;
    }
    String uri = "socket://" + ip;
    String name = JFAWT.getString("Enter Printer Name", getPrinterName(""));
    ShellProcess sp = new ShellProcess();
    String ppd = getPPD();
    if (ppd.equals("Auto")) {
      JFAWT.showError("Error", "Must specify a printer make/model");
      return;
    }
    String output = sp.run(new String[] {"sudo", "lpadmin", "-E", "-p", name, "-v", uri, "-m", ppd}, false);
    if (sp.getErrorLevel() != 0) {
      JFLog.log("cmd=" + sp.command);
      JFAWT.showError("Error", "Unable to add printer:\n"+output);
    }
    dispose();
  }

  private void addSharedPrinter() {
    String ip = ipAddr.getText();
    if (ip.length() == 0) return;
    if (ppdList.isEmpty()) {
      JFAWT.showError("Error", "Must specify a printer make/model");
      return;
    }
    String uri = "smb://" + user.getText();
    String password = new String(pass.getPassword());
    if (password.length() > 0) uri += ":" + password;
    uri += "@" + server.getText() + "/" + share.getText();
    String name = JFAWT.getString("Enter Printer Name", getPrinterName(""));
    ShellProcess sp = new ShellProcess();
    String ppd = getPPD();
    if (ppd.equals("Auto")) {
      JFAWT.showError("Error", "Must specify a printer make/model");
      return;
    }
    String output = sp.run(new String[] {"sudo", "lpadmin", "-E", "-p", name, "-v", uri, "-m", ppd}, false);
    if (sp.getErrorLevel() != 0) {
      JFLog.log("cmd=" + sp.command);
      JFAWT.showError("Error", "Unable to add printer:\n"+output);
    }
    dispose();
  }

  private void setPosition() {
    Rectangle s = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
    Dimension d = getSize();
    setLocation(s.width/2 - d.width/2, s.height/2 - (d.height/2));
  }
}
